iT邦幫忙

0

[C#] Base32 編碼/解碼方法 不分大小寫的編碼方式

  • 分享至 

  • xImage
  •  

前陣子在教學一篇 Base64 及 Base64Url 編碼 的方法,有提到可以將網址上傳送的資料採用 Base64 編碼。

但今天遇到一個特別的問題,因為網站上某些網址已經被搜尋引擎收錄,偶爾會有一些爬蟲程式到我的頁面上,而爬蟲程式使用的網址竟然全改為小寫,而我原本使用大小寫有別的 Base64 參數,造成解碼錯誤。

例如我原網址為: /Index/StraInfo/MTk0
參數 MTk0 可被 Base64 解碼

可是爬蟲程式呼叫網址為: /index/straInfo/mtk0
程式收到的參數為 mtk0 經過 Base64 解碼就無法正確還原了。

為了讓爬蟲程式使用全小寫網址可以正常瀏覽我的網站,我將原本 Base64 編碼的方式改為 Base32 編碼。
Base32 編碼為不分大小寫的編碼方式,編碼後可用的字母為
abcdefghijklmnopqrstuvwxyz234567

使用 Base32 編碼結果放在網址上當參數,也不會因為對方更改大小寫而造成解碼錯誤

Base32 編碼與解碼的方法

以下是我使用 Base32 編碼與解碼的方法

/// <summary>
/// Base 32 編碼
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public string EncodeBase32(string value)
{
	if (string.IsNullOrEmpty(value)) return null;

	string Alphabet = "abcdefghijklmnopqrstuvwxyz234567";
	var valueBytes = Encoding.UTF8.GetBytes(value);
	var encodedBuilder = new StringBuilder();
	var position = 0;
	var left = 0;
	for (var i = 0; i < valueBytes.Length * 8 / 5 + (valueBytes.Length * 8 % 5 == 0 ? 0 : 1); i++)
	{
		var encodedByte = default(byte);
		if (left > 0)
		{
			encodedByte |= (byte)(valueBytes[position] << (8 - left));
			if (left <= 5 && position < valueBytes.Length - 1)
			{
				position++;
				if (left < 5) encodedByte |= (byte)(valueBytes[position] >> left);
			}
		}
		else
		{
			encodedByte |= valueBytes[position];
		}
		encodedBuilder.Append(Alphabet[(byte)(encodedByte >> 3)]);
		left = 8 * (position + 1) - 5 * (i + 1);
	}
	return encodedBuilder.ToString();
}

/// <summary>
/// Base 32 解碼
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public string DecodeBase32(string value)
{
	if (string.IsNullOrEmpty(value)) return null;
	string Alphabet = "abcdefghijklmnopqrstuvwxyz234567";
	value = value.ToLower().TrimEnd('=');

	var decodedBytes = new byte[value.Length * 5 / 8];
	var position = 0;
	var available = 0;

	for (var i = 0; i < value.Length; i++)
	{
		var symbol = (byte)(Alphabet.IndexOf(value[i]) << 3);
		if (available > 0)
		{
			decodedBytes[position] |= (byte)(symbol >> (8 - available));
			if (available <= 5 && position < decodedBytes.Length - 1)
			{
				decodedBytes[++position] |= (byte)(symbol << available);
			}
		}
		else
		{
			decodedBytes[position] |= symbol;
		}
		available = 8 * (position + 1) - 5 * (i + 1);
	}
	return Encoding.UTF8.GetString(decodedBytes);
}

程式碼中的語法
string Alphabet = "abcdefghijklmnopqrstuvwxyz234567";
可以修改為
string Alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
這樣編碼結果字母就可以為全大寫。

Base32 優缺點比較

使用 Base32 當網址參數有幾個好處

  1. 適用不分大小寫的環境
  2. 數字少了 0, 1 ,避免與 O, I 混淆
  3. 當網址參數不需要用 HttpUtility.UrlEncode() 再編碼

而缺點的話包含

  1. 編碼後長度膨脹約 60%,比 Base64 膨脹 33% 還多。
  2. 在 .Net 沒有內建支援的方法,需要自己寫。
  3. 並非為常見編碼方式

有關 Base32 的編碼說明可以參考維基百科

相關學習文章

[C#] Convert.ToBase64String 基本轉碼及適用網址參數轉碼延伸應用


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言